--****
--minimal wrap of 
-- GNU Scientific Library
--http://ftp.gnu.org/gnu/gsl/
--http://gnuwin32.sourceforge.net/packages/gsl.htm
--
-- really only a few routines of
-- * gsl permute_ ~*
-- * gsl combination_ ~*
-- * gsl_histogram2d_ ~*
-- * gsl_histogram_ ~*


/* 
 * 
 * Copyright (C) 1996, 1997, 1998, 1999, 2000 Brian Gough
 * 
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation; either version 2 of the License, or (at
 * your option) any later version.
 * 
 * This program is distributed in the hope that it will be useful, but
 * WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 * General Public License for more details.
 * 
 * You should have received a copy of the GNU General Public License
 * along with this program; if not, write to the Free Software
 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
 */

include std/dll.e
include std/machine.e
include std/convert.e
--~ include qt/debug_utils.e

--~ include qt/core.e
include qt/wrap_helpers.e


ifdef WINDOWS then
	constant hGsl = open_dll("libgsl.dll")
elsifdef UNIX then
	constant hGsl = open_dll("libgsl.so")
elsedef
	puts(2, "OS not supported\n")
	abort(1)
end ifdef


constant

    hQt_gsl_permutation_calloc = define_c_func(hGsl, stdcall&"gsl_permutation_calloc", {I}, P),
    hQt_gsl_permutation_init = define_c_proc(hGsl, stdcall&"gsl_permutation_init", {P}),
    hQt_gsl_permutation_free = define_c_proc(hGsl, stdcall&"gsl_permutation_free", {P}),

    hQt_gsl_permutation_next = define_c_func(hGsl, stdcall&"gsl_permutation_next", {P}, I),
    hQt_gsl_permutation_valid = define_c_func(hGsl, stdcall&"gsl_permutation_valid", {P}, I),
    hQt_gsl_permutation_reverse = define_c_proc(hGsl, stdcall&"gsl_permutation_reverse", {P}),
    hQt_gsl_permutation_fprintf = define_c_func(hGsl, stdcall&"gsl_permutation_fprintf", {P, P, CP}, I),

    hQt_gsl_combination_calloc = define_c_func(hGsl, stdcall&"gsl_combination_calloc", {I, I}, P),
    hQt_gsl_combination_init_last = define_c_proc(hGsl, stdcall&"gsl_combination_init_last", {P}),
    hQt_gsl_combination_init_first = define_c_proc(hGsl, stdcall&"gsl_combination_init_first", {P}),
    hQt_gsl_combination_free = define_c_proc(hGsl, stdcall&"gsl_combination_free", {P}),
    hQt_gsl_combination_n = define_c_func(hGsl, stdcall&"gsl_combination_n", {P}, I),
    hQt_gsl_combination_k = define_c_func(hGsl, stdcall&"gsl_combination_k", {P}, I),
    hQt_gsl_combination_valid = define_c_func(hGsl, stdcall&"gsl_combination_valid", {P}, I),
    hQt_gsl_combination_prev = define_c_func(hGsl, stdcall&"gsl_combination_prev", {P}, I),
    hQt_gsl_combination_next = define_c_func(hGsl, stdcall&"gsl_combination_next", {P}, I),
    hQt_gsl_combination_fprintf = define_c_func(hGsl, stdcall&"gsl_combination_fprintf", {P, P, CP}, I),

    --2d
    hQt_gsl_histogram2d_calloc = define_c_func(hGsl, stdcall&"gsl_histogram2d_calloc", {I, I}, P),
    hQt_gsl_histogram2d_calloc_uniform = define_c_func(hGsl, stdcall&"gsl_histogram2d_calloc_uniform", {I, I, F, F, F, F}, P),
    hQt_gsl_histogram2d_free = define_c_proc(hGsl, stdcall&"gsl_histogram2d_free", {P}),
    hQt_gsl_histogram2d_reset = define_c_proc(hGsl, stdcall&"gsl_histogram2d_reset", {P}),
    hQt_gsl_histogram2d_fprintf = define_c_func(hGsl, stdcall&"gsl_histogram2d_fprintf", {P, P, CP, CP}, I),
    hQt_gsl_histogram2d_increment = define_c_func(hGsl, stdcall&"gsl_histogram2d_increment", {P, F, F}, I),
    hQt_gsl_histogram2d_set_ranges_uniform = define_c_func(hGsl, stdcall&"gsl_histogram2d_set_ranges_uniform", {P, F, F, F, F}, I),

    --1d
    hQt_gsl_histogram_calloc = define_c_func(hGsl, stdcall&"gsl_histogram_calloc", {I}, P),
    hQt_gsl_histogram_calloc_uniform = define_c_func(hGsl, stdcall&"gsl_histogram_calloc_uniform", {I, F, F}, P),
    hQt_gsl_histogram_free = define_c_proc(hGsl, stdcall&"gsl_histogram_free", {P}),
    hQt_gsl_histogram_reset = define_c_proc(hGsl, stdcall&"gsl_histogram_reset", {P}),
    hQt_gsl_histogram_fprintf = define_c_func(hGsl, stdcall&"gsl_histogram_fprintf", {P, P, CP, CP}, I),
    hQt_gsl_histogram_increment = define_c_func(hGsl, stdcall&"gsl_histogram_increment", {P, F}, I),
    hQt_gsl_histogram_set_ranges_uniform = define_c_func(hGsl, stdcall&"gsl_histogram_set_ranges_uniform", {P, F, F}, I),

    $


public enum GSL_SUCCESS = 0
     ,GSL_FAILURE = -1
--~ #define GSL_ERROR(x1,x2,x3) do {} while(0)

-- GSL_RANGE_CHECK_OFF  ??
-- HAVE_INLINE ??
--~ GSL_EDOM




  
  --~ gsl_rng_env_setup ();
  --~ T = gsl_rng_default;
  --~ r = gsl_rng_alloc (T);


  --~ gsl_ieee_env_setup ();
  --~ gsl_set_error_handler (&my_error_handler);
--~ static void
--~ my_error_handler (const char *reason, const char *file, int line, int err)


public constant have_gsl = 1 --hQt_gsl >0

--~ struct gsl_permutation_struct
--~ {
  --~ size_t size;
  --~ size_t *data;
--~ };

--~ typedef struct gsl_permutation_struct gsl_permutation;

--~ gsl_permutation *gsl_permutation_alloc (const size_t n);

--~ gsl_permutation *gsl_permutation_calloc (const size_t n);
--**
--returns an atom gsl_perm to be used in other routines
--must call gsl_perm_free when done
public function gsl_permutation_calloc(integer n)
    return c_func(hQt_gsl_permutation_calloc, {n})
end function


--~ void gsl_permutation_init (gsl_permutation * p);
public procedure gsl_permutation_init(atom gsl_perm)
    c_proc(hQt_gsl_permutation_init, {gsl_perm})
end procedure

--~ void gsl_permutation_free (gsl_permutation * p);
public procedure gsl_permutation_free(atom gsl_perm)
	c_proc(hQt_gsl_permutation_free, {gsl_perm})
end procedure


--~ int gsl_permutation_memcpy (gsl_permutation * dest, const gsl_permutation * src);

--~ int gsl_permutation_fread (FILE * stream, gsl_permutation * p);
--~ int gsl_permutation_fwrite (FILE * stream, const gsl_permutation * p);
--~ int gsl_permutation_fscanf (FILE * stream, gsl_permutation * p);
--~ int gsl_permutation_fprintf (FILE * stream, const gsl_permutation * p, const char *format);
public function gsl_permutation_fprintf(object stream, atom gsl_perm, object fformat="%u")
     atom pformat=allocate_string(fformat, 1)
    --~ if sequence(stream) then
        --~ stream = open(stream, "w", 1)
    --~ elsif stream < 1 then 
        --~ stream = stdFILE(1) 
    --~ elsif stream < 3 then 
        --~ stream = stdFILE(stream) 
    --~ end if
    return c_func(hQt_gsl_permutation_fprintf, {stream, gsl_perm, pformat})
end function

--~ size_t gsl_permutation_size (const gsl_permutation * p);
--~ size_t * gsl_permutation_data (const gsl_permutation * p);

--~ size_t gsl_permutation_get (const gsl_permutation * p, const size_t i);
--~ int gsl_permutation_swap (gsl_permutation * p, const size_t i, const size_t j);

--~ int gsl_permutation_valid (gsl_permutation * p);
public function gsl_permutation_valid(atom gsl_perm)
    return c_func(hQt_gsl_permutation_valid, {gsl_perm})
end function

--~ void gsl_permutation_reverse (gsl_permutation * p);
public procedure gsl_permutation_reverse(atom gsl_perm)
	c_proc(hQt_gsl_permutation_reverse, {gsl_perm})
end procedure


--~ int gsl_permutation_inverse (gsl_permutation * inv, const gsl_permutation * p);
--~ int gsl_permutation_next (gsl_permutation * p);
public function gsl_permutation_next(atom gsl_perm)
    return c_func(hQt_gsl_permutation_next, {gsl_perm})
end function
--~ int gsl_permutation_prev (gsl_permutation * p);
--~ int gsl_permutation_mul (gsl_permutation * p, const gsl_permutation * pa, const gsl_permutation * pb);

--~ int gsl_permutation_linear_to_canonical (gsl_permutation * q, const gsl_permutation * p);
--~ int gsl_permutation_canonical_to_linear (gsl_permutation * p, const gsl_permutation * q);

--~ size_t gsl_permutation_inversions (const gsl_permutation * p);
--~ size_t gsl_permutation_linear_cycles (const gsl_permutation * p);
--~ size_t gsl_permutation_canonical_cycles (const gsl_permutation * q);


--~ GSL_VAR int gsl_check_range;

--~ #ifdef HAVE_INLINE

--~ extern inline
--~ size_t
--~ gsl_permutation_get (const gsl_permutation * p, const size_t i)
--~ {
--~ #ifndef GSL_RANGE_CHECK_OFF
  --~ if (i >= p->size)
    --~ {
      --~ GSL_ERROR_VAL ("index out of range", GSL_EINVAL, 0);
    --~ }
--~ #endif
  --~ return p->data[i];
--~ }

--~ #endif /* HAVE_INLINE */



--~ struct gsl_combination_struct
--~ {
  --~ size_t n;
  --~ size_t k;
  --~ size_t *data;
--~ };





--~ typedef struct gsl_combination_struct gsl_combination;

--~ gsl_combination *gsl_combination_alloc (const size_t n, const size_t k);
--~ gsl_combination *gsl_combination_calloc (const size_t n, const size_t k);
--**
--returns an atom gsl_comb to be used in other routines
--must call gsl_comb_free when done
public function gsl_combination_calloc(integer n,integer k)
        
    return c_func(hQt_gsl_combination_calloc, {n, k})
end function

--~ void gsl_combination_init_first (gsl_combination * c);
public procedure gsl_combination_init_first(atom gsl_comb)
        c_proc(hQt_gsl_combination_init_first, {gsl_comb})
end procedure



--returns an atom gsl_perm to be used in other routines
--must call gsl_comb_free when done
--~ void gsl_combination_init_last (gsl_combination * c);
public procedure gsl_combination_init_last(atom gsl_comb)
        c_proc(hQt_gsl_combination_init_last, {gsl_comb})
end procedure

--~ void gsl_combination_free (gsl_combination * c);
public procedure gsl_combination_free(atom gsl_comb)
	c_proc(hQt_gsl_combination_free, {gsl_comb})
end procedure

--~ int gsl_combination_fread (FILE * stream, gsl_combination * c);
--~ int gsl_combination_fwrite (FILE * stream, const gsl_combination * c);
--~ int gsl_combination_fscanf (FILE * stream, gsl_combination * c);

--~ int gsl_combination_fprintf (FILE * stream, const gsl_combination * c, const char *format);
public function gsl_combination_fprintf(object stream, atom gsl_comb, object fformat="%u")
     atom pformat=allocate_string(fformat, 1)

    return c_func(hQt_gsl_combination_fprintf, {stream, gsl_comb, pformat})
end function


--~ size_t gsl_combination_n (const gsl_combination * c);
public function gsl_combination_n(atom gsl_comb)
    return c_func(hQt_gsl_combination_n, {gsl_comb})
end function

--~ size_t gsl_combination_k (const gsl_combination * c);
public function gsl_combination_k(atom gsl_comb)
    return c_func(hQt_gsl_combination_k, {gsl_comb})
end function

--~ size_t * gsl_combination_data (const gsl_combination * c);

--~ size_t gsl_combination_get (const gsl_combination * c, const size_t i);

--~ int gsl_combination_valid (gsl_combination * c);
public function gsl_combination_valid(atom gsl_comb)
    return c_func(hQt_gsl_combination_valid, {gsl_comb})
end function


--~ int gsl_combination_next (gsl_combination * c);
public function gsl_combination_next(atom gsl_comb)
    return c_func(hQt_gsl_combination_next, {gsl_comb})
end function
--~ int gsl_combination_prev (gsl_combination * c);
public function gsl_combination_prev(atom gsl_comb)
    return c_func(hQt_gsl_combination_prev, {gsl_comb})
end function

--~ GSL_VAR int gsl_check_range;

--~ #ifdef HAVE_INLINE

--~ extern inline
--~ size_t
--~ gsl_combination_get (const gsl_combination * c, const size_t i)
--~ {
--~ #ifndef GSL_RANGE_CHECK_OFF
  --~ if (i >= c->k)
    --~ {
      --~ GSL_ERROR_VAL ("index out of range", GSL_EINVAL, 0);
    --~ }
--~ #endif
  --~ return c->data[i];
--~ }

--~ #endif /* HAVE_INLINE */


--~ typedef struct {
  --~ size_t nx, ny ;
  --~ double * xrange ;
  --~ double * yrange ;
  --~ double * bin ;
--~ } gsl_histogram2d ;

--~ typedef struct {
  --~ size_t nx, ny ;
  --~ double * xrange ;
  --~ double * yrange ;
  --~ double * sum ;
--~ } gsl_histogram2d_pdf ;

--~  gsl_histogram2d * gsl_histogram2d_alloc (const size_t nx, const size_t ny);
--~  gsl_histogram2d * gsl_histogram2d_calloc (const size_t nx, const size_t ny);
public function gsl_histogram2d_calloc(integer nx, integer ny)
        return c_func(hQt_gsl_histogram2d_calloc, {nx, ny})
end function

public function gsl_histogram_calloc(integer n)
        return c_func(hQt_gsl_histogram_calloc, {n})
end function

--~  gsl_histogram2d * gsl_histogram2d_calloc_uniform (const size_t nx, const size_t ny,
                                                             --~ const double xmin, const double xmax,
                                                             --~ const double ymin, const double ymax);
public function gsl_histogram2d_calloc_uniform(
            integer nx, integer ny
           , atom xmin, atom xmax
           , atom ymin, atom ymax
            )
    return c_func(hQt_gsl_histogram2d_calloc_uniform, {
                   nx, ny
                     ,xmin, xmax
                       ,ymin, ymax
                       })
end function

public function gsl_histogram_calloc_uniform(
            integer n
           , atom xmin, atom xmax
            )
    return c_func(hQt_gsl_histogram_calloc_uniform, {
                   n
                     ,xmin, xmax
                       })
end function

--~  void gsl_histogram2d_free (gsl_histogram2d * h);
public procedure gsl_histogram2d_free(atom gsl_histo2)
	c_proc(hQt_gsl_histogram2d_free, {gsl_histo2})
end procedure

public procedure gsl_histogram_free(atom gsl_histo)
	c_proc(hQt_gsl_histogram_free, {gsl_histo})
end procedure

--~  int gsl_histogram2d_increment (gsl_histogram2d * h, double x, double y);
public function gsl_histogram2d_increment(atom gsl_histo2, atom x, atom y)
    return c_func(hQt_gsl_histogram2d_increment, {gsl_histo2, x, y})
end function

public function gsl_histogram_increment(atom gsl_histo, atom x)
    return c_func(hQt_gsl_histogram_increment, {gsl_histo, x})
end function

--~  int gsl_histogram2d_accumulate (gsl_histogram2d * h,
                                           --~ double x, double y, double weight);
--~  int gsl_histogram2d_find (const gsl_histogram2d * h,
                                     --~ const double x, const double y, size_t * i, size_t * j);

--~  double gsl_histogram2d_get (const gsl_histogram2d * h, const size_t i, const size_t j);
--~  int gsl_histogram2d_get_xrange (const gsl_histogram2d * h, const size_t i,
                                           --~ double * xlower, double * xupper);
--~  int gsl_histogram2d_get_yrange (const gsl_histogram2d * h, const size_t j,
                                           --~ double * ylower, double * yupper);


--~  double gsl_histogram2d_xmax (const gsl_histogram2d * h);
--~  double gsl_histogram2d_xmin (const gsl_histogram2d * h);
--~  size_t gsl_histogram2d_nx (const gsl_histogram2d * h);

--~  double gsl_histogram2d_ymax (const gsl_histogram2d * h);
--~  double gsl_histogram2d_ymin (const gsl_histogram2d * h);
--~  size_t gsl_histogram2d_ny (const gsl_histogram2d * h);

--~  void gsl_histogram2d_reset (gsl_histogram2d * h);
public procedure gsl_histogram2d_reset(atom gsl_histo2)
	c_proc(hQt_gsl_histogram2d_reset, {gsl_histo2})
end procedure

public procedure gsl_histogram_reset(atom gsl_histo)
	c_proc(hQt_gsl_histogram_reset, {gsl_histo})
end procedure


--~ 
--~ gsl_histogram2d *
--~ gsl_histogram2d_calloc_range(size_t nx, size_t ny,
                             --~ double *xrange, double *yrange);

--~ 
--~ int
--~ gsl_histogram2d_set_ranges_uniform (gsl_histogram2d * h,
                                    --~ double xmin, double xmax,
                                    --~ double ymin, double ymax);
public function gsl_histogram2d_set_ranges_uniform(atom gsl_histo2
           , atom xmin, atom xmax
           , atom ymin, atom ymax
            )
    return c_func(hQt_gsl_histogram2d_set_ranges_uniform, {gsl_histo2
                          ,xmin, xmax
                         ,ymin, ymax
                       })
end function

public function gsl_histogram_set_ranges_uniform(atom gsl_histo
           , atom xmin, atom xmax
            )
    return c_func(hQt_gsl_histogram_set_ranges_uniform, {gsl_histo
                          ,xmin, xmax
                       })
end function


--~ 
--~ int
--~ gsl_histogram2d_set_ranges (gsl_histogram2d * h,
                            --~ const double xrange[], size_t xsize,
                            --~ const double yrange[], size_t ysize);

--~ 
--~ int
--~ gsl_histogram2d_memcpy(gsl_histogram2d *dest, const gsl_histogram2d *source);

--~ 
--~ gsl_histogram2d *
--~ gsl_histogram2d_clone(const gsl_histogram2d * source);

--~ 
--~ double
--~ gsl_histogram2d_max_val(const gsl_histogram2d *h);

--~ 
--~ void
--~ gsl_histogram2d_max_bin (const gsl_histogram2d *h, size_t *i, size_t *j);

--~ 
--~ double
--~ gsl_histogram2d_min_val(const gsl_histogram2d *h);

--~ 
--~ void
--~ gsl_histogram2d_min_bin (const gsl_histogram2d *h, size_t *i, size_t *j);

--~ 
--~ double
--~ gsl_histogram2d_xmean (const gsl_histogram2d * h);

--~ 
--~ double
--~ gsl_histogram2d_ymean (const gsl_histogram2d * h);

--~ 
--~ double
--~ gsl_histogram2d_xsigma (const gsl_histogram2d * h);

--~ 
--~ double
--~ gsl_histogram2d_ysigma (const gsl_histogram2d * h);

--~ 
--~ double
--~ gsl_histogram2d_cov (const gsl_histogram2d * h);

--~ 
--~ double
--~ gsl_histogram2d_sum (const gsl_histogram2d *h);

--~ 
--~ int
--~ gsl_histogram2d_equal_bins_p(const gsl_histogram2d *h1,
                             --~ const gsl_histogram2d *h2) ;

--~ 
--~ int
--~ gsl_histogram2d_add(gsl_histogram2d *h1, const gsl_histogram2d *h2);

--~ 
--~ int
--~ gsl_histogram2d_sub(gsl_histogram2d *h1, const gsl_histogram2d *h2);

--~ 
--~ int
--~ gsl_histogram2d_mul(gsl_histogram2d *h1, const gsl_histogram2d *h2);

--~ 
--~ int
--~ gsl_histogram2d_div(gsl_histogram2d *h1, const gsl_histogram2d *h2);

--~ 
--~ int
--~ gsl_histogram2d_scale(gsl_histogram2d *h, double scale);

--~ 
--~ int
--~ gsl_histogram2d_shift(gsl_histogram2d *h, double shift);

--~  int gsl_histogram2d_fwrite (FILE * stream, const gsl_histogram2d * h) ;
--~  int gsl_histogram2d_fread (FILE * stream, gsl_histogram2d * h);
--~  int gsl_histogram2d_fprintf (FILE * stream, const gsl_histogram2d * h,
                                        --~ const char * range_format,
                                        --~ const char * bin_format);
public function gsl_histogram2d_fprintf(object stream, atom gsl_histo2, object range_format="%u", object bin_format="%u")
     atom prange_format=allocate_string(range_format, 1)
     atom pbin_format=allocate_string(bin_format, 1)
    return c_func(hQt_gsl_histogram2d_fprintf, {stream, gsl_histo2, prange_format, pbin_format})
end function

public function gsl_histogram_fprintf(object stream, atom gsl_histo, object range_format="%u", object bin_format="%u")
     atom prange_format=allocate_string(range_format, 1)
     atom pbin_format=allocate_string(bin_format, 1)
    return c_func(hQt_gsl_histogram_fprintf, {stream, gsl_histo, prange_format, pbin_format})
end function

--~  int gsl_histogram2d_fscanf (FILE * stream, gsl_histogram2d * h);

--~  gsl_histogram2d_pdf * gsl_histogram2d_pdf_alloc (const size_t nx, const size_t ny);
--~  int gsl_histogram2d_pdf_init (gsl_histogram2d_pdf * p, const gsl_histogram2d * h);
--~  void gsl_histogram2d_pdf_free (gsl_histogram2d_pdf * p);
--~  int gsl_histogram2d_pdf_sample (const gsl_histogram2d_pdf * p,
                                           --~ double r1, double r2, 
                                           --~ double * x, double * y);
  
